﻿using Newtonsoft.Json;

namespace TiaoTiaoCode.Common.Extensions
{
    /// <summary>
    /// 对象扩展
    /// </summary>
    public static class ObjectEx
    {
        /// <summary>
        /// 对象深拷贝
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static T TiaoTiaoDeepClone<T>(this T obj) where T : class
        {
            return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(obj))!;
        }

        /// <summary>
        /// 对象复制
        /// 可用于父类转子类
        /// </summary>
        /// <typeparam name="TSrc">源对象</typeparam>
        /// <typeparam name="TDesc">目标对象</typeparam>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static TDesc TiaoTiaoCopy<TSrc, TDesc>(this TSrc obj) where TSrc : class where TDesc : class
        {
            return JsonConvert.DeserializeObject<TDesc>(JsonConvert.SerializeObject(obj))!;
        }

        /// <summary>
        /// 对象转JsonString
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static string TiaoTiaoToJson(this object? obj)
        {
            return JsonConvert.SerializeObject(obj);
        }

        /// <summary>
        /// 字符串转对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="s"></param>
        /// <returns></returns>
        public static T? TiaoTiaoToObj<T>(this string s)
        {
            return JsonConvert.DeserializeObject<T>(s);
        }

        #region Safe转换

        /// <summary>
        /// 安全转字符串
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static string TiaoTiaoSafeTo(this object? obj, string defaultValue = "")
        {
            if (obj == null) return defaultValue;

            return obj.ToString();
        }

        /// <summary>
        /// 安全转Int32
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static int TiaoTiaoSafeTo(this object? obj, int defaultValue = 0)
        {
            if (obj == null) return defaultValue;

            if (!int.TryParse(obj.ToString(), out var i)) return defaultValue;

            return i;
        }

        /// <summary>
        /// 安全转Short
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static short TiaoTiaoSafeTo(this object? obj, short defaultValue = 0)
        {
            if (obj == null) return defaultValue;

            if (!short.TryParse(obj.ToString(), out var i)) return defaultValue;

            return i;
        }

        /// <summary>
        /// 安全转UInt32
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static uint TiaoTiaoSafeTo(this object? obj, uint defaultValue = 0)
        {
            if (obj == null) return defaultValue;

            if (!uint.TryParse(obj.ToString(), out var i)) return defaultValue;

            return i;
        }

        /// <summary>
        /// 安全转UShort
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static ushort TiaoTiaoSafeTo(this object? obj, ushort defaultValue = 0)
        {
            if (obj == null) return defaultValue;

            if (!ushort.TryParse(obj.ToString(), out var i)) return defaultValue;

            return i;
        }

        /// <summary>
        /// 安全转Long
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static long TiaoTiaoSafeTo(this object? obj, long defaultValue = 0)
        {
            if (obj == null) return defaultValue;

            if (!long.TryParse(obj.ToString(), out var i)) return defaultValue;

            return i;
        }

        /// <summary>
        /// 安全转ULong
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static ulong TiaoTiaoSafeTo(this object? obj, ulong defaultValue = 0)
        {
            if (obj == null) return defaultValue;

            if (!ulong.TryParse(obj.ToString(), out var i)) return defaultValue;

            return i;
        }

        /// <summary>
        /// 安全转float
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static float TiaoTiaoSafeTo(this object? obj, float defaultValue = 0)
        {
            if (obj == null) return defaultValue;

            if (!float.TryParse(obj.ToString(), out var i)) return defaultValue;

            return i;
        }

        /// <summary>
        /// 安全转double
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static double TiaoTiaoSafeTo(this object? obj, double defaultValue = 0)
        {
            if (obj == null) return defaultValue;

            if (!double.TryParse(obj.ToString(), out var i)) return defaultValue;

            return i;
        }

        /// <summary>
        /// 安全转decimal
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static decimal TiaoTiaoSafeTo(this object? obj, decimal defaultValue = 0)
        {
            if (obj == null) return defaultValue;

            if (!decimal.TryParse(obj.ToString(), out var i)) return defaultValue;

            return i;
        }

        /// <summary>
        /// 安全转bool
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static bool TiaoTiaoSafeTo(this object? obj, bool defaultValue = false)
        {
            if (obj == null) return defaultValue;

            if (!bool.TryParse(obj.ToString(), out var i)) return defaultValue;

            return i;
        }

        #endregion
    }
}
